using System.Security.Cryptography;
using System.Text;
using Admin2025.Domain.Entities.App;
using Admin2025.Domain.Repositories;

namespace Admin2025.Application.Services;

/// <summary>
/// 认证服务，包含用户注册和登录逻辑。
/// </summary>
public class AuthService
{
    private readonly IRepository<AppUser> _userRep;
    private readonly IRepository<AppRole> _roleRep;
    public AuthService(IRepository<AppUser> userRep, IRepository<AppRole> roleRep)
    {
        _userRep = userRep;
        _roleRep = roleRep;
    }

    /// <summary>
    /// 用户注册
    /// </summary>
    /// <param name="username">用户名</param>
    /// <param name="password">明文密码</param>
    /// <returns>注册后的用户实体</returns>
    public async Task<AppUser> RegisterAsync(string username, string password)
    {
        // 检查用户名是否已存在
        var exists = (await _userRep.GetAllAsync()).Any(u => u.Username == username);
        if (exists)
            throw new Exception("用户名已存在");

        // 生成盐
        var salt = Guid.NewGuid().ToString("N");
        // 密码加密
        var hash = ComputeHash(password, salt);

        var user = new AppUser
        {
            Username = username,
            Passwprd = hash,
            Salt = salt
        };

        return await _userRep.CreateAsync(user);
    }

    /// <summary>
    /// 用户登录
    /// </summary>
    /// <param name="username">用户名</param>
    /// <param name="password">明文密码</param>
    /// <returns>登录成功返回用户实体，否则抛出异常</returns>
    public async Task<AppUser> LoginAsync(string username, string password)
    {
        var user = (await _userRep.GetAllAsync()).FirstOrDefault(u => u.Username == username);
        if (user == null)
            throw new Exception("用户不存在");

        var hash = ComputeHash(password, user.Salt);
        if (user.Passwprd != hash)
            throw new Exception("密码错误");

        return user;
    }

    // 密码加密方法
    private string ComputeHash(string password, string salt)
    {
        using var sha256 = SHA256.Create();
        var bytes = Encoding.UTF8.GetBytes(password + salt);
        var hash = sha256.ComputeHash(bytes);
        return Convert.ToBase64String(hash);
    }
}